package com.fhs.trans.extend;

import com.fhs.common.utils.StringUtil;
import com.fhs.core.trans.vo.VO;
import com.fhs.trans.service.impl.SimpleTransService;
import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.mybatis.Mappers;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.table.IdInfo;
import com.mybatisflex.core.table.TableInfo;
import com.mybatisflex.core.table.TableInfoFactory;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.util.List;
import java.util.Set;

/**
 * Mybatis-Flex 简单翻译驱动。
 *
 * @author wanglei
 * @author wangshuai
 */
@Slf4j
@SuppressWarnings({"rawtypes", "unchecked"})
public class MybatisFlexSimpleTransDiver implements SimpleTransService.SimpleTransDiver {

    @Override
    public List<? extends VO> findByIds(List<? extends Serializable> ids, Class<? extends VO> targetClass, String uniqueField) {
        return this.findByIds(ids, targetClass, uniqueField, (Set)null);
    }

    @Override
    public List<? extends VO> findByIds(List<? extends Serializable> ids, Class<? extends VO> targetClass, String uniqueField, Set<String> targetFields) {
        TableInfo tableInfo = TableInfoFactory.ofEntityClass(targetClass);
        uniqueField = this.getUniqueField(tableInfo, uniqueField);
        QueryWrapper queryWrapper = genWrapper(tableInfo, targetFields, uniqueField);
        queryWrapper.where(getQueryColumn(tableInfo, uniqueField).in(ids));
        return getMapper(targetClass).selectListByQuery(queryWrapper);
    }

    @Override
    public VO findById(Serializable id, Class<? extends VO> targetClass, String uniqueField) {
        return this.findById(id, targetClass, uniqueField, (Set)null);
    }

    @Override
    public VO findById(Serializable id, Class<? extends VO> targetClass, String uniqueField, Set<String> targetFields) {
        TableInfo tableInfo = TableInfoFactory.ofEntityClass(targetClass);
        uniqueField = this.getUniqueField(tableInfo, uniqueField);
        QueryWrapper queryWrapper = genWrapper(tableInfo, targetFields, uniqueField);
        queryWrapper.where(getQueryColumn(tableInfo, uniqueField).in(id));
        return (VO)getMapper(targetClass).selectOneById(id);

    }


    private String getUniqueField(TableInfo tableInfo, String uniqueField) {
        if (!StringUtil.isEmpty(uniqueField)) {
            return uniqueField;
        }
        return getKeyProperty(tableInfo);
    }

    /**
     * 获取主键属性。
     *
     * @param tableInfo 表信息
     * @return 主键属性
     */
    private String getKeyProperty(TableInfo tableInfo) {
        List<IdInfo> primaryKeyList = tableInfo.getPrimaryKeyList();
        // 类中没有使用 @Id 注解标记主键
        if (primaryKeyList.isEmpty()) {
            throw new IllegalArgumentException(String.format("类 %s 中没有找到 @Id 定义的主键，请使用 uniqueField 指定主键。", tableInfo.getEntityClass().getName()));
        }
        // MyBatis-Flex 支持多主键，这里只返回按照定义顺序的第一个主键。
        return primaryKeyList.get(0).getProperty();
    }


    private QueryWrapper genWrapper(TableInfo tableInfo, Set<String> targetFields, String uniqueField) {
        QueryWrapper queryWrapper = QueryWrapper.create();
        if (targetFields != null && !targetFields.isEmpty()) {
            targetFields.add(getKeyProperty(tableInfo));
            if (!StringUtil.isEmpty(uniqueField)) {
                targetFields.add(uniqueField);
            }
            queryWrapper.select(targetFields.stream()
                    .map(tableInfo::getColumnByProperty)
                    .map(tableInfo::getQueryColumnByProperty)
                    .toArray(QueryColumn[]::new));
        }
        return queryWrapper;
    }

    private QueryColumn getQueryColumn(TableInfo tableInfo, String field) {
        String column = tableInfo.getColumnByProperty(field);
        return tableInfo.getQueryColumnByProperty(column);
    }

    public BaseMapper getMapper(Class entity) {
        return Mappers.ofEntityClass(entity);
    }

}
